#include "Rp2AviGenerator.h"
#include "Rp2Platform.h"

using namespace Rp2;
//---------------------------------------------------------------------------------------------------
AVIGenerator::AVIGenerator(std::string kFileName, int iFrameRate)
{
	m_kFileName			= kFileName;
	m_iFrameRate		= iFrameRate;
	m_pAVIFile			= 0;
	m_pStream			= 0;
	m_pStreamCompressed = 0;
	memset(&m_kBIH, 0, sizeof(BITMAPINFOHEADER));
}
//---------------------------------------------------------------------------------------------------
AVIGenerator::~AVIGenerator()
{
	assert(m_pStream==NULL);
	assert(m_pStreamCompressed==NULL);
	assert(m_pAVIFile==NULL);
}
//---------------------------------------------------------------------------------------------------
bool AVIGenerator::InitAVIEngine()
{
	AVISTREAMINFO streamInfo; // information for a single stream 
	AVICOMPRESSOPTIONS opts;
	AVICOMPRESSOPTIONS FAR* aOpts[1] = {&opts};
	
	HRESULT hr;

	// Step 0 : Let's make sure we are running on 1.1 
	DWORD wVer = HIWORD(VideoForWindowsVersion());
	if (wVer < 0x010a)
	{
		 // oops, we are too old, blow out of here 
		assert(false);
	}

	// Step 1 : initialize AVI engine
	AVIFileInit();

	// Step 2 : Open the movie file for writing....
	hr = AVIFileOpen(&m_pAVIFile,			// Address to contain the new file interface pointer
		       (tCHAR*)m_kFileName.c_str(),	// Null-terminated string containing the name of the file to open
		       OF_WRITE | OF_CREATE,	    // Access mode to use when opening the file. 
		       NULL);						// use handler determined from file extension.
											// Name your file .avi -> very important
	
	if (hr != AVIERR_OK)
	{
		assert(false);
	}

	// Fill in the header for the video stream....
	memset(&streamInfo, 0, sizeof(streamInfo));
	streamInfo.fccType                = streamtypeVIDEO;	// video stream type
	streamInfo.fccHandler             = 0;
	streamInfo.dwScale                = 1;					// should be one for video
	streamInfo.dwRate                 = m_iFrameRate;		// fps
	streamInfo.dwSuggestedBufferSize  = m_kBIH.biSizeImage;	// Recommended buffer size, in bytes, for the stream.
	SetRect(&streamInfo.rcFrame, 0, 0,						// rectangle for stream
	    (int) m_kBIH.biWidth,
	    (int) m_kBIH.biHeight);
	
	// Step 3 : Create the stream;
	hr = AVIFileCreateStream(m_pAVIFile,	// file pointer
							 &m_pStream,	// returned stream pointer
							 &streamInfo);	// stream header
	if (hr != AVIERR_OK)
	{
		assert(false);
	}

	// Step 4: Get codec and infos about codec
	memset(&opts, 0, sizeof(opts));
	// Poping codec dialog
	if (!AVISaveOptions(NULL, 0, 1, &m_pStream, (LPAVICOMPRESSOPTIONS FAR *) &aOpts))
	{
		AVISaveOptionsFree(1,(LPAVICOMPRESSOPTIONS FAR *) &aOpts);
		assert(false);
		return S_FALSE;
	}

	// Step 5:  Create a compressed stream using codec options.
	hr = AVIMakeCompressedStream(&m_pStreamCompressed, 
				m_pStream, 
				&opts, 
				NULL);
	if (hr != AVIERR_OK)
	{
		assert(false);
	}

	// releasing memory allocated by AVISaveOptionFree
	hr=AVISaveOptionsFree(1,(LPAVICOMPRESSOPTIONS FAR *) &aOpts);
	if (hr!=AVIERR_OK)
	{
		assert(false);
	}

	// Step 6 : sets the format of a stream at the specified position
	hr = AVIStreamSetFormat(m_pStreamCompressed, 
					0,														// position
					&m_kBIH,												// stream format
					m_kBIH.biSize +	m_kBIH.biClrUsed * sizeof(RGBQUAD));	// format size
	if (hr != AVIERR_OK)
	{
		assert(false);
	}

	// Step 7 : Initialize step counter
	m_lFrameCounter = 0;	

	return true;
}
//---------------------------------------------------------------------------------------------------
void AVIGenerator::ReleaseAVIEngine()
{
	if (m_pStream)
	{
		AVIStreamRelease(m_pStream);
		m_pStream=NULL;
	}

	if (m_pStreamCompressed)
	{
		AVIStreamRelease(m_pStreamCompressed);
		m_pStreamCompressed=NULL;
	}

	if (m_pAVIFile)
	{
		AVIFileRelease(m_pAVIFile);
		m_pAVIFile=NULL;
	}

	// Close engine
	AVIFileExit();	
}
//---------------------------------------------------------------------------------------------------
void AVIGenerator::SetBitmapHeader(LPBITMAPINFOHEADER lpBIH)
{
	// checking that bitmap size are multiple of 4
	assert(lpBIH->biWidth%4==0);
	assert(lpBIH->biHeight%4==0);

	// copying bitmap info structure.
	memcpy(&m_kBIH,lpBIH, sizeof(BITMAPINFOHEADER));
}
//---------------------------------------------------------------------------------------------------
void AVIGenerator::SetRate(int iFrameRate)
{
	m_iFrameRate = iFrameRate;
}
//---------------------------------------------------------------------------------------------------
LPBITMAPINFOHEADER AVIGenerator::GetBitmapHeader()
{
	return &m_kBIH;
}
//---------------------------------------------------------------------------------------------------
void AVIGenerator::AddFrame(BYTE* pBits)
{
	HRESULT hr;

	// compress bitmap
	hr = AVIStreamWrite(m_pStreamCompressed,	// stream pointer
		m_lFrameCounter,						// time of this frame
		1,										// number to write
		pBits,									// image buffer
		m_kBIH.biSizeImage,						// size of this frame
		AVIIF_KEYFRAME,							// flags....
		NULL,
		NULL);

	// updating frame counter
	m_lFrameCounter++;
}
//---------------------------------------------------------------------------------------------------